#ifndef SOUND_H
#define SOUND_H
#include <iostream>
#include <cstdint>
#include <fstream>
#include <cstddef>
#include <cstring>
#include <string>
#include <exception>
#include <cmath>
#include <array>
#include <functional>
#include <sstream>

using std::int16_t;
using std::int32_t;
using std::ifstream;

class file_not_found_exception : public std::exception
{
    std::string description;
public:
    file_not_found_exception(const std::string& filename)
        : description("File \"" + filename + "\" not found.")
    {}
    virtual char const* what() const throw()
    {
        return description.data();
    }
};
class parse_exception : public std::exception
{
public:
    virtual char const* what() const throw()
    {
        return "This format has not been supported yet.";
    }
};

#pragma pack(2)
struct sound
{
    char riff[4];
    int32_t size;
    char wavefmt[8];
    int32_t pcm_bytes;
    int16_t format;
    int16_t channel;
    int32_t frequency;
    int32_t bytes_per_second;
    int16_t block;
    int16_t bits;
    char* additional_information = nullptr;
    bool has_fact;
    int32_t fact_bytes;
    char* fact;
    int32_t data_bytes;
    union
    {
        int8_t* _8;
        int16_t* _16;
        char* _c;
    } data;

    sound();
    sound(const std::string& filename);
    friend std::ostream& operator<<(std::ostream& o, const sound& s);
    std::string statistic_description();

    int32_t data_count;
    double average();
    double mean_squared(double average_value = NAN, double var = NAN);
    double variance(double average_value = NAN, double ms = NAN);
    void load_file(const std::string& filename);
    double seconds();
//    std::array<double, 8192> power_spectrum_real_part();
    double normalized(int i);
};
#pragma pack()

#endif // SOUND_H
